package com.duguo.dynamicmvc.factory.processor.controller;

import java.util.Map;

import javassist.CtClass;
import javassist.CtMethod;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;

import com.duguo.dynamicmvc.factory.ControllerFactory;
import com.duguo.dynamicmvc.factory.utils.BeanUtils;
import com.duguo.dynamicmvc.support.pathinfo.PathInfo;

public class ControllerNameBuilderImpl implements  BeanFactoryAware,ControllerNameBuilder{
	

    static final String PREFIX_CONTROLLER_CLASS       = "ControllerClass";
    static final String PREFIX_MULTI_CONTROLLER_CLASS = "MultiCtrlrClass";
    private BeanFactory _beanFactory;

	public boolean isRootController(String controllerPath) {
        return "/".equals(controllerPath);
    }

    public String getChildPath(String parentPath, String controllerPath) {
        return controllerPath.substring(parentPath.length());
    }

    public String getSameLevelPath(PathInfo pathInfo, String controllerPath) {
    	int level=getControllerLevel(controllerPath);
        return pathInfo.getPaths(level);
    }

    public boolean isMultiLevelName(String controllerName) {
        return controllerName.indexOf("/") > 0;
    }


    public String getFirstLevelName(String controllerName) {
        return controllerName.substring(0, controllerName.indexOf("/"));
    }
    


    public String getParentLevelName(String controllerName) {
        if (controllerName.endsWith("/")) {
            controllerName = controllerName.substring(0, controllerName.length() - 1);
        }
        if(controllerName.length()==0){
        	return "/";
        }
        controllerName=controllerName.substring(0, controllerName.lastIndexOf("/"));
        if(controllerName.length()==0){
        	return "/";
        }
        return controllerName+"/";
    }

    public int getControllerLevel(String controllerName) {
        if (controllerName.equals("/")) {
            return 1;
        }
        if (!controllerName.endsWith("/")) {
            controllerName = controllerName + "/";
        }
        return controllerName.split("/").length;
    }

    public String getLastLevelName(String controllerName) {
        controllerName = getNormalizedName(controllerName);
        if (controllerName.lastIndexOf("/") > 0)
            return controllerName.substring(controllerName.lastIndexOf("/") + 1);
        else
            return controllerName;
    }

    public String getRemainLevelName(String controllerName) {
        return controllerName.substring(controllerName.indexOf("/") + 1);
    }
    

    
	/*
	 * method based helper method
	 */
    public boolean isDo(String methodName) {
    	return methodName.matches(".*(/do[A-Z]).*");
    }
    public boolean isSetter(String methodName) {
    	return methodName.matches("(set[A-Z]).*");
    }

    public String getDoDefaultViewName(String methodName) {
    	methodName=methodName.substring(2);
    	methodName=methodName.substring(0,1).toLowerCase()+methodName.substring(1);
        return methodName;
    }


    public String getControllerPath(String controllerClassName){
    	String rootControllerClassName=getControllerInternalRootClassName();
    	if(controllerClassName.length()==rootControllerClassName.length()){
    		return "/";
    	}
    	controllerClassName=controllerClassName.substring(rootControllerClassName.length()-7);
        StringBuffer sb = new StringBuffer("/");
        String[] paths=controllerClassName.split("\\.");
        if(paths.length>1){
	        for(int i=0;i<paths.length-1;i++){
	        	sb.append(paths[i].substring(7));
	        	sb.append("/");
	        }
        }
    	sb.append(paths[paths.length-1].substring(PREFIX_CONTROLLER_CLASS.length()));
    	sb.append("/");
        return sb.toString();
    }

    public String getControllerInternalInterfaceName(CtMethod targetCtMethod)throws Exception{
        StringBuffer sb = new StringBuffer(ControllerFactory.class.getPackage().getName());
        sb.append(".internal.");
        for (CtClass param : targetCtMethod.getParameterTypes()) {
            sb.append(param.getSimpleName());
        }
        sb.append("Interface");
        return sb.toString();
    }

    public String getControllerInternalRootClassName(){
        StringBuffer sb = new StringBuffer(ControllerFactory.class.getPackage().getName());
        sb.append(".internal.");
        sb.append("MultiCtrlrClassroot");
        return sb.toString();
    }

    public String getControllerInternalClassName(String parentControllerName,String controllerPath, boolean isMultiActionController){
    	StringBuffer sb = new StringBuffer();
    	sb.append(parentControllerName.substring(0,parentControllerName.lastIndexOf(".")));
    	sb.append(".package");
    	sb.append(parentControllerName.substring(parentControllerName.lastIndexOf(".")+16));
    	
    	if(controllerPath.startsWith("/"))
    		controllerPath=controllerPath.substring(1);
    	String[] paths=controllerPath.split("/");
    	if(paths.length>1){
    		for(int i=0;i<paths.length-1;i++){
    			sb.append(".package");
    			sb.append(paths[i]);
    		}
    	}
    	sb.append("."+ (isMultiActionController?PREFIX_MULTI_CONTROLLER_CLASS:PREFIX_CONTROLLER_CLASS));
    	sb.append(paths[paths.length-1]);
        return sb.toString();
    }


    public String getControllerParentClassName(String controllerClassName){
    	controllerClassName=controllerClassName.substring(0,controllerClassName.lastIndexOf("."));
		String simpleName=controllerClassName.substring(controllerClassName.lastIndexOf(".")+8);
		if(simpleName.equals("root"))
			return getControllerInternalRootClassName();
		controllerClassName=controllerClassName.substring(0,controllerClassName.lastIndexOf("."));
		controllerClassName=controllerClassName+"."+PREFIX_MULTI_CONTROLLER_CLASS+simpleName;
        return controllerClassName;
    }

    public String getNormalizedName(String controllerName) {
        if (controllerName.startsWith("/")) {
            controllerName = controllerName.substring(1);
        }

        if (controllerName.endsWith("/")) {
            controllerName = controllerName.substring(0, controllerName.length() - 1);
        }
        return controllerName;
    }

	public Object getParentController(Object currentController) {
		String currentControllerPath=getControllerPath(currentController.getClass().getName());
    	if(currentControllerPath.length()>1){
    		String parentControllerPath=getParentLevelName(currentControllerPath);
    		return getControllerByPath(parentControllerPath);    		
    	}
		return null;
	}

	Object getControllerByPath(String controllerPath) {
		Object selectedController=_beanFactory.getBean("/");
		if(controllerPath.length()==1){
			return selectedController;
		}
		String[] controllerNames=controllerPath.split("/");
		for(String controllerName:controllerNames){
			if(controllerName.length()==0){
				continue;
			}
			Map controllers=BeanUtils.getFieldValue(selectedController, "registedControllers", Map.class);
	    	if(controllers.containsKey(controllerName)){
	    		selectedController=controllers.get(controllerName);
	    	}else{
	    		selectedController=BeanUtils.getFieldValue(selectedController, "dynamicController", Object.class);
	    		if(selectedController!=null){
	    			String dynamicControllerName=getControllerPath(selectedController.getClass().getName());
		    		if(!dynamicControllerName.endsWith(controllerName+"/")){
		    			throw new RuntimeException("Cannot find controller:"+controllerPath);
		    		}
		    	}else{
		    		throw new RuntimeException("Cannot find controller:"+controllerPath);
		    	}
	    	}
		}
		return selectedController;
	}

	public void setBeanFactory(BeanFactory beanFactory) {
		_beanFactory = beanFactory;
	}
}
